package nancal.mp.service

import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.MultiFormatWriter
import com.google.zxing.WriterException
import com.google.zxing.client.j2se.MatrixToImageWriter
import com.warrenstrange.googleauth.GoogleAuthenticator
import com.warrenstrange.googleauth.GoogleAuthenticatorConfig.GoogleAuthenticatorConfigBuilder
import com.warrenstrange.googleauth.GoogleAuthenticatorKey
import com.warrenstrange.googleauth.ICredentialRepository
import nbcp.base.utils.UrlUtil
import org.springframework.stereotype.Component
import org.springframework.stereotype.Service
import java.io.ByteArrayOutputStream
import java.net.URLEncoder
import java.nio.charset.StandardCharsets
import java.util.*

class GoogleDefaultCredentialRepository : ICredentialRepository {
    override fun getSecretKey(p0: String?): String {
        return ""
    }

    override fun saveUserCredentials(p0: String?, p1: String?, p2: Int, p3: MutableList<Int>?) {

    }

}

@Service
class GoogleAuthenticatorService {
    lateinit var googleAuthenticator: GoogleAuthenticator

    init {
        val config = GoogleAuthenticatorConfigBuilder()
//            .setTimeStepSizeInMillis(60_000)
            .setCodeDigits(6)
            .setWindowSize(3) // 设置时间窗口大小为3个30秒的时间步长
            .build()

        this.googleAuthenticator = GoogleAuthenticator(config)
        this.googleAuthenticator.credentialRepository = GoogleDefaultCredentialRepository();
    }

    fun createSecretKey(username: String): GoogleAuthenticatorKey {
        return googleAuthenticator.createCredentials(username)
    }

    @Throws(WriterException::class)
    fun getQRCodeUrl(secretKey: String, accountName: String, issuer: String): String {
        var platformName = UrlUtil.encodeURIComponent(issuer)
        val qrCodeData =
            "otpauth://totp/${platformName}:${UrlUtil.encodeURIComponent(accountName)}?secret=${secretKey}&issuer=${platformName}"
        //&period=60

        val hints: MutableMap<EncodeHintType, Any?> = HashMap()
        hints[EncodeHintType.CHARACTER_SET] = "UTF-8"

        val matrix = MultiFormatWriter().encode(
            qrCodeData,
            BarcodeFormat.QR_CODE,
            200,
            200,
            hints
        )

        val pngOutputStream = ByteArrayOutputStream()
        MatrixToImageWriter.writeToStream(matrix, "PNG", pngOutputStream)
        return "data:image/png;base64," + Base64.getEncoder().encodeToString(pngOutputStream.toByteArray())
    }

    fun authorize(secretKey: String, verificationCode: Int): Boolean {
        return googleAuthenticator.authorize(secretKey, verificationCode)
    }
}
